package com.lambkit.db.sql;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import cn.hutool.core.util.StrUtil;
import com.lambkit.db.meta.ColumnMeta;
import com.lambkit.db.meta.TableMeta;

public class SqlConcatGroup {

    public ColumnsGroup filter(ColumnsGroup columnsGroup, String json, TableMeta tableMeta) {
        JSONObject jsonObj = JSON.parseObject(json);
        filter(columnsGroup, jsonObj, tableMeta);
        return columnsGroup;
    }

    public ColumnsGroup filter(ColumnsGroup columnsGroup, JSONObject jsonObj, TableMeta tableMeta) {
        if(jsonObj!=null) {
            for(String field : jsonObj.keySet()) {
                if(StrUtil.isBlank(field)) {
                    continue;
                }
                if("$and".equalsIgnoreCase(field)) {
                    ColumnsGroup group = new ColumnsGroup();
                    group.filter(jsonObj.getJSONObject(field), tableMeta);
                    columnsGroup.columnsWithAnd(group);
                } else if("$or".equalsIgnoreCase(field)) {
                    ColumnsGroup group = new ColumnsGroup();
                    group.filter(jsonObj.getJSONObject(field), tableMeta);
                    columnsGroup.columnsWithOr(group);
                } else {
                    if(field.contains("@")) {
                        String[] flds = field.split("@");
                        //使用ColumnMeta控制field，如果field不存在，则忽略
                        ColumnMeta columnMeta = tableMeta!=null ? tableMeta.getColumn(flds[0]) : null;
                        if (columnMeta!= null) {
                            if(flds.length > 0) {
                                String type = StrUtil.isNotBlank(flds[1]) ? flds[1].toLowerCase() : null;
                                filter(columnsGroup, flds[0], jsonObj.getString(field), type, true);
                            } else {
                                filter(columnsGroup, flds[0], jsonObj.getString(field), columnMeta);
                            }
                        } else {
                            columnsGroup.getWarns().add("field:" + flds[0] + " not found in meta");
                        }
                    } else {
                        //使用ColumnMeta控制field，如果field不存在，则忽略
                        ColumnMeta columnMeta = tableMeta!=null ? tableMeta.getColumn(field) : null;
                        if (columnMeta!= null) {
                            filter(columnsGroup, field, jsonObj.getString(field), columnMeta);
                        } else {
                            columnsGroup.getWarns().add("field:" + field + " not found in meta");
                        }
                    }
                }
            }
        }
        return columnsGroup;
    }

    public ColumnsGroup filter(ColumnsGroup columnsGroup, String field, String value, ColumnMeta columnMeta) {
        if(StrUtil.isNotBlank(field)) {
            String javatype = columnMeta!=null ? columnMeta.getJavaType() : "java.lang.String";
            filter(columnsGroup, field, value, javatype, true);
        }
        return columnsGroup;
    }

    public ColumnsGroup filter(ColumnsGroup columnsGroup, String field, String value, String type, boolean javaType) {
        if(StrUtil.isNotBlank(value)) {
            String info = value.trim();
//			if(info.startsWith("!")) {
//				info = info.substring(1).trim();
//			}
            if(info.startsWith("(") && info.endsWith(")")) {
                //多个过滤条件
                //info = info.substring(1, info.length()-1);
                //Printer.print(this, "db"("filter: " + info);
                filterGroup(columnsGroup, field, info, type, 0, javaType);
            } else {
                Columns columns = new Columns();
                columns.filter(field, value, type, javaType);
                columnsGroup.columnsWithAnd(columns);
            }
        }
        return columnsGroup;
    }


    /**
     * 解析 ((item) & (item)) | (item)
     * @param columnsGroup
     * @param field
     * @param value
     * @param type
     * @param junc
     */
    protected void filterGroup(ColumnsGroup columnsGroup, String field, String value, String type, int junc, boolean javaType) {
        //Printer.print(this, "db"("filter: " + value);
        if(StrUtil.isBlank(value)) {
            return;
        }
        if(value.startsWith(")")) {
            value = value.substring(1).trim();
            filterGroup(columnsGroup, field, value, type, junc, javaType);
            return;
        }
        //((item) & (item)) | (item)
        //(item) & (item)) | (item)
        if(value.startsWith("(")) {
            value = value.substring(1).trim();
            if(value.startsWith("(")) {
                //(item) & (item)) | (item)
                ColumnsGroup colg = new ColumnsGroup();
                filterGroup(colg, field, value, type, junc, javaType);
                if(junc==0) {
                    columnsGroup.columnsWithAnd(colg);
                } else {
                    columnsGroup.columnsWithOr(colg);
                }
            } else {
                filterGroup(columnsGroup, field, value, type, junc, javaType);
            }
        } else if(value.startsWith("&")) {
            //& (item)) | (item)
            value = value.substring(1).trim();
            filterGroup(columnsGroup, field, value, type, 0, javaType);
        } else if(value.startsWith("|")){
            //| (item)
            value = value.substring(1).trim();
            filterGroup(columnsGroup, field, value, type, 1, javaType);
        } else {
            //item) & (item)) | (item)
            int t = value.indexOf(")");
            if(t>0) {
                String tval = value.substring(0, t);
                Columns col = new Columns();
                col.filter(field, tval, type, javaType);
                if(junc==0) {
                    columnsGroup.columnsWithAnd(col);
                } else {
                    columnsGroup.columnsWithOr(col);
                }
                value = value.substring(t+1).trim();
                //Printer.print(this, "db"("filter: " + value);
                filterGroup(columnsGroup, field, value, type, junc, javaType);
            }
        }
    }
}
